package com.sec.etech.bpm.cust.controller;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sec.etech.bpm.cust.dto.EtechBpmTask;
import com.sec.etech.bpm.cust.mapper.EtechTaskOpinionExtMapper;
import com.sec.etech.bpm.cust.model.EtechTaskOpinionExt;
import com.sec.etech.bpm.cust.service.EtechBpmHelper;
import com.sec.etech.bpm.cust.service.EtechBpmService;
import com.sec.etech.org.dto.EtechUserDto;
import com.sec.etech.org.service.EtechUserService;
import com.sec.etech.org.service.EtechUserUtil;
import com.sec.etech.sys.cal.service.WorkCalService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.openbpm.base.api.aop.annotion.CatchErr;
import org.openbpm.base.api.response.impl.ResultMsg;
import org.openbpm.base.core.util.AppUtil;
import org.openbpm.base.core.util.StringUtil;
import org.openbpm.bpm.api.engine.action.cmd.FlowRequestParam;
import org.openbpm.bpm.api.engine.data.result.BpmFlowData;
import org.openbpm.bpm.api.engine.data.result.BpmFlowTaskData;
import org.openbpm.bpm.api.engine.data.result.FlowData;
import org.openbpm.bpm.api.model.nodedef.Button;
import org.openbpm.bpm.api.model.task.IBpmTask;
import org.openbpm.bpm.core.manager.BpmTaskManager;
import org.openbpm.bpm.core.manager.TaskIdentityLinkManager;
import org.openbpm.bpm.core.model.BpmTask;
import org.openbpm.bpm.core.model.TaskIdentityLink;
import org.openbpm.bpm.rest.controller.BpmTaskController;
import org.openbpm.sys.api.model.DefaultIdentity;
import org.openbpm.sys.api.model.SysIdentity;
import org.openbpm.sys.util.ContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@RestController
@RequestMapping({"/etech/task"})
@Api(description = "流程任务相关服务接口")
@Slf4j
public class EtechTaskController extends BpmTaskController {

    @Resource
    EtechTaskOpinionExtMapper taskOpinionExtMapper;
    @Autowired
    TaskIdentityLinkManager taskIdentityLinkManager;

    @Autowired
    BpmTaskManager bpmTaskManager;

    @Autowired
    WorkCalService workCalService;
    @Autowired
    EtechUserService etechUserService;
    @Autowired
    EtechBpmService etechBpmService;


    public ResultMsg<FlowData> getTaskDataReal(String taskId, String formType){
        ResultMsg<FlowData> resultMsg = null;
        try {
            resultMsg = super.getTaskData(taskId, formType);
        } catch (Exception e) {
            log.debug(e.getMessage());
        }
        if (resultMsg != null && resultMsg.getIsOk()) {
            BpmFlowData flowData = (BpmFlowData) resultMsg.getData();


            //检查是否任务超期，如是则修改提交信息必填
            EtechTaskOpinionExt taskOpinionExt = taskOpinionExtMapper.selectOne(new LambdaQueryWrapper<EtechTaskOpinionExt>().eq(EtechTaskOpinionExt::getTaskId, taskId));
            if (taskOpinionExt != null && taskOpinionExt.getRemainDays() != null) {
                if (taskOpinionExt.getRemainDays() < 0) {
                    flowData.getConfigSpecified().setRequiredOpinion(true);
                    flowData.getConfigSpecified().put("requiredOpinion", Boolean.TRUE);
                }
            }

            // 上汽标准立项流程特殊逻辑：K11 节点处理意见必填
            String bpmKey = taskOpinionExt.getDefKey();
            String taskKey = taskOpinionExt.getTaskKey();
            List<String> requiredList = Arrays.asList("K11", "K13", "K13.1");
            if ("BPM_SamSecsSetup".equals(bpmKey) && (requiredList.indexOf(taskKey) > -1)) {
                flowData.getConfigSpecified().put("requiredOpinion", Boolean.TRUE);
            }

            // RD 课题立项 流程所有审批意见必填
            if ("BPM_RandsTaskSetup".equals(bpmKey)) {
                flowData.getConfigSpecified().put("requiredOpinion", Boolean.TRUE);
            }

            //检查是否添加超管调整（角色-流程管理员）  流程管理员 flow_admin
            if (ContextUtil.currentUserIsAdmin() || EtechUserUtil.checkUserHasRole("flow_admin")) {
                List<Button> buttonList = flowData.getButtonList();
                buttonList.add(createTaskModifyButton());
                if (!ContextUtil.currentUserIsAdmin()) {
                    // TODO 增加超管跳转/超管终止
                }

            }

            flowData.setButtonList(flowData.getButtonList().stream()
                    .filter(btn -> !"signOppose,addSign".contains(btn.getAlias()))
                    .peek(btn -> {
                        if (btn.getName().equals("会签同意")) {
                            btn.setName("提交");
                        }
                    }).collect(Collectors.toList()));

            if (flowData instanceof BpmFlowTaskData) {
                // 增加任务返回数据，包含taskOpinionExt
                IBpmTask task = ((BpmFlowTaskData) flowData).getTask();
                if (taskOpinionExt != null) {
                    EtechBpmTask task1 = new EtechBpmTask();
                    BeanUtil.copyProperties(taskOpinionExt, task1);
                    BeanUtil.copyProperties(task, task1);
                    ((BpmFlowTaskData) flowData).setTask(task1);
                }
            }
        }
        return resultMsg;
    }

    @RequestMapping(value = {"getTaskData"}, method = {RequestMethod.POST, RequestMethod.GET})
    @CatchErr
    @ApiOperation(value = "获取流程任务相关数据", notes = "获取任务的业务数据、表单、按钮、权限等信息，为了渲染展示任务页面")
    public ResultMsg<FlowData> getTaskData(@RequestParam @ApiParam(value = "任务ID", required = true) String taskId, @RequestParam(required = false) @ApiParam(value = "表单类型", defaultValue = "pc") String formType) throws Exception {
        return getTaskDataReal(taskId, formType);
    }

    private Button createTaskModifyButton() {
        Button button = new Button();
        button.setName("超管修改");
        button.setAlias("taskModify");
        button.setConfigPage("/bpm/task/adminOperation.html");
        return button;
    }

    @RequestMapping(value = {"getTaskOpinionExt"}, method = {RequestMethod.GET})
    @CatchErr
    @ApiOperation(value = "获取流程节点任务Opinion相关数据", notes = "获取流程节点的到期日期、处理人，为了渲染展示任务页面")
    public ResultMsg getTaskOpinionExt(@RequestParam @ApiParam(value = "taskOpinion表主键") String taskId) throws Exception {
        JSONObject jsonObject = new JSONObject();
        EtechTaskOpinionExt taskOpinionExt = taskOpinionExtMapper.selectOne(new LambdaQueryWrapper<EtechTaskOpinionExt>().eq(EtechTaskOpinionExt::getTaskId, taskId));
        List<TaskIdentityLink> linkList = taskIdentityLinkManager.getByTaskId(taskOpinionExt.getTaskId());
        JSONArray jsonArray = new JSONArray();
        if (linkList != null && linkList.size() > 0) {
            for (TaskIdentityLink link : linkList) {
                JSONObject object = new JSONObject();
                if ("user".equals(link.getType())) {
                    EtechUserDto user = etechUserService.getUserInfoById(link.getIdentity());
                    object.put("linkId", link.getId());
                    object.put("userId", user.getUserId());
                    object.put("userName", user.getFullname());
                    object.put("account", user.getAccount());
                    object.put("groupName", user.getDprtName());
                    jsonArray.add(object);
                }
            }
        }
        jsonObject.put("taskOpinionExt", taskOpinionExt);
        jsonObject.put("userList", jsonArray);
        return this.getSuccessResult(jsonObject);
    }


    @RequestMapping(value = {"updateTaskOpinionExt"}, method = {RequestMethod.POST})
    @CatchErr
    @ApiOperation(value = "更新流程节点任务Opinion相关数据", notes = "更新流程节点的到期日期、处理人、剩余天数、工作天数")
    public ResultMsg updateTaskOpinionExt(@RequestBody JSONObject jsonObject) throws Exception {
        if (jsonObject == null || jsonObject.getJSONObject("taskOpinionExt") == null) {
            return this.getWarnResult("操作失败，请检查参数");
        }

        String opinion = jsonObject.getString("opinion");

        // 0 获取参数
        EtechTaskOpinionExt taskOpinionExt = JSONObject.toJavaObject(jsonObject.getJSONObject("taskOpinionExt"), EtechTaskOpinionExt.class);
        JSONArray addUserArr = jsonObject.getJSONArray("addUserList");
        String delUsers = jsonObject.getString("delUserList");
        Date planComplateDate = taskOpinionExt.getPlanCompleteDay();
        String masterGroup = taskOpinionExt.getMasterGroup();
        String masterGroupName = taskOpinionExt.getMasterGroupName();

        // 针对石潇铭做限制，
        if (ContextUtil.getCurrentUserId().equals("1399")) {
            if (taskOpinionExt.getTaskName() != null && taskOpinionExt.getTaskName().startsWith("A8")) {
                // pass
            } else {
                return this.getWarnResult("仅可修改修改单的A8处理人节点");
            }
        }

        taskOpinionExt = taskOpinionExtMapper.selectById(taskOpinionExt.getId());



        // 1 修改人员
        // 特别注意 多候选人 bpm_task.assignee_id_=0
        // bug fix 针对单候选人替换需要验证
        if (StringUtil.isNotEmpty(delUsers)) {//删除处理人
            taskIdentityLinkManager.removeByIdList(new ArrayList<>(Arrays.asList(delUsers.split(","))));
        }
        if (addUserArr != null && addUserArr.size() > 0) {//增加处理人
            Map<String, String> userMap = new HashMap<>();//数据库中的处理人
            List<TaskIdentityLink> oldLinklist = taskIdentityLinkManager.getByTaskId(taskOpinionExt.getTaskId());
            if (oldLinklist != null && oldLinklist.size() > 0) {
                for (TaskIdentityLink link : oldLinklist) {
                    if ("user".equalsIgnoreCase(link.getType())) {
                        userMap.put(link.getIdentity(), link.getIdentity());
                    }
                }
            }
            List<SysIdentity> taskIdentitys = new ArrayList<>();
            for (int i = 0; i < addUserArr.size(); i++) {
                JSONObject obj = addUserArr.getJSONObject(i);
                if (!userMap.containsKey(obj.getString("userId")) && StringUtil.isNotEmpty(obj.getString("userId")) && obj.getLong("userId") > 0) {//过滤已存在的人员
                    taskIdentitys.add(new DefaultIdentity(obj.getString("userId"), obj.getString("userName"), "user"));
                }
            }
            if (taskIdentitys.size() > 0) {
                BpmTask task = bpmTaskManager.get(taskOpinionExt.getTaskId());
                //多候选人模式，fix 单候选人替换
                if (task != null) {
                    if (task.getAssigneeId() == null || !"0".equals(task.getAssigneeId())) {
                        task.setAssigneeId("0");
                        bpmTaskManager.update(task);
                    }
                    taskIdentityLinkManager.createIdentityLink(task, taskIdentitys);
                }
            }
        }
        List<TaskIdentityLink> linklist = taskIdentityLinkManager.getByTaskId(taskOpinionExt.getTaskId());
        StringBuffer assignInfo = new StringBuffer();
        if (linklist != null && linklist.size() > 0) {
            for (TaskIdentityLink link : linklist) {
                if ("user".equalsIgnoreCase(link.getType())) {
                    assignInfo.append(link.getType()).append("-").append(link.getIdentityName()).append("-").append(link.getIdentity()).append(",");
                }
            }
        }
        if (assignInfo.length() > 0) {//处理人
            taskOpinionExt.setAssignInfo(assignInfo.toString());
        }

        // 2. 修改责任部门
        if (StringUtil.isNotEmpty(masterGroup)) {
            taskOpinionExt.setMasterGroup(masterGroup);
            taskOpinionExt.setMasterGroupName(masterGroupName);
        }

        // 3. 修改预期完成时间
        if (planComplateDate != null) {
            planComplateDate = WorkCalService.endOfDay(planComplateDate);
            taskOpinionExt.setPlanCompleteDay(planComplateDate);
            int remainDays = workCalService.getWorkDaysByTime4remainDay(new Date(), taskOpinionExt.getPlanCompleteDay());
            taskOpinionExt.setRemainDays(remainDays);
            taskOpinionExt.setCalDaysTime(new Date());
        }

        if (Strings.isNotBlank(opinion)){
            taskOpinionExt.setOpinion(opinion);
        }



        // 处理转办任务
        etechBpmService.handleTurnTask(jsonObject);

        int num = taskOpinionExtMapper.updateById(taskOpinionExt);
        return num > 0 ? this.getSuccessResult() : this.getWarnResult("操作失败");
    }

    @RequestMapping(
            value = {"doAction"},
            method = {RequestMethod.POST}
    )
    @CatchErr
    @ApiOperation(
            value = "执行任务相关动作",
            notes = "执行任务相关的动作 如：同意，驳回，反对，锁定，解锁，转办，会签任务等相关操作"
    )
    public ResultMsg<String> doAction(@RequestBody FlowRequestParam flowParam) throws Exception {
        Map<String, String> map = etechBpmService.doAction(flowParam);
        return this.getSuccessResult(String.format("执行%s操作成功", map.get("resultMsg")));
        /*BpmTask task = bpmTaskManager.get(flowParam.getTaskId());

        if (flowParam.getAction().equals("agree")){
            // TODO 拦截保存，尝试干点什么, 可能会炸
            if (task != null){
                List<String> action = actionMap.getAgreeAction(task.getNodeId());
                if (action != null){
                    log.info("get action:" + action);
                    String businessKey = action.get(0);
                    String beanKey = action.get(1);
                    JSONObject data = flowParam.getData();
                    log.info("get data:" + data);
                    if (data.containsKey(businessKey)){
                        LifeCycle lifeCycle = SpringUtil.getBean(beanKey, LifeCycle.class);
                        if (lifeCycle != null){
                            if (lifeCycle.checkPermission(null, null, data)) {
                                lifeCycle.beforeSave(null, null, data);
                                if (data != null) {
                                    // 检查公用更新字段
                                    for (String key1 : data.keySet()) {
                                        JSONObject itemJson = data.getJSONObject(key1);
                                        FormDefDataUtil.checkCommonUpdateDate(itemJson);
                                        data.put(key1, itemJson);
                                    }
                                }
                                JSONObject result = this.formDefDataService.saveFormDefData(data, beanKey, false);
                                log.info("get result:" + result);
                                lifeCycle.afterSave(null, null, data);
                            }  else {
                                throw new Exception(lifeCycle.permissionDenied());
                            }
                            log.info("完成我的拦截方法");
                            return this.getSuccessResult(String.format("执行%s操作成功", "保存"));
                        }
                    }
                }
            }


        }

        DefualtTaskActionCmd taskModel = new DefualtTaskActionCmd(flowParam);
        String actionName = taskModel.executeCmd();

        // 执行完成后操作
        if (flowParam.getAction().equals("oppose")) {
            // TODO
            if (task != null) {
                BpmFormActionMap.OpposeAction action = actionMap.getOpposeAction(task.getNodeId());
                JSONObject data = flowParam.getData();
                if (action != null) {
                    if (data.containsKey(action.getBusinessKey())) {
                        String id = data.getJSONObject(action.getBusinessKey()).getString(action.getBusinessId());
                        action.getAction().accept(id);
                    }
                }
            }
        }

        // 自动完成节点？
        // nodeId,taskId
        JSONObject jsonObject = etechBpmHelper.getAutoSubmitTask();
        if(jsonObject!=null){
            flowParam.setTaskId(jsonObject.getString("taskId"));
            flowParam.setAction(ActionType.AGREE.getKey());
            taskModel = new DefualtTaskActionCmd(flowParam);
            IUser currentUser = ContextUtil.getCurrentUser();
            ContextUtil.setCurrentUser(EtechUserUtil.getUserAdmin());
            actionName = taskModel.executeCmd();
            ContextUtil.setCurrentUser(currentUser);
            etechBpmHelper.removeAutoSubmitTaskInThread();
        }
        //新启动另外流程
        JSONObject startObject = etechBpmHelper.getStartNewBpmInst();
        if(startObject!=null){
            FlowRequestParam newFlowParam = JSONObject.toJavaObject(startObject, FlowRequestParam.class);
            DefaultInstanceActionCmd instanceCmd = new DefaultInstanceActionCmd(newFlowParam);
            actionName = instanceCmd.executeCmd();
            String instanceId = instanceCmd.getInstanceId();
            //调用回掉方法
            JSONObject callBackParam = startObject.getJSONObject("callBack");
            if(callBackParam!=null){//方法回调，增加参数
                JSONObject params = callBackParam.getJSONObject("params");
                if(params!=null){
                    callBackParam.getJSONObject("params").put("instanceId", instanceId);
                }else{
                    params = new JSONObject();
                    params.put("instanceId", instanceId);
                    callBackParam.put("params", params);
                }
                etechBpmHelper.callBack(callBackParam);
            }
            etechBpmHelper.removeStartNewBpmInstInThread();
        }
        return this.getSuccessResult(String.format("执行%s操作成功", actionName));*/
    }


    @RequestMapping("getDbTaskData")
    public ResultMsg getDbTaskData(@RequestParam("taskId") String taskId) {
        try {
            return ResultMsg.SUCCESS(taskOpinionExtMapper.selectOne(
                    new LambdaQueryWrapper<EtechTaskOpinionExt>().eq(EtechTaskOpinionExt::getTaskId, taskId)
            ));
        } catch (Exception e) {
            return ResultMsg.ERROR(e.getMessage());
        }
    }

    @RequestMapping(
            value = {"saveAutoSubmitTask"},
            method = {RequestMethod.POST, RequestMethod.GET}
    )
    @CatchErr
    @ApiOperation(
            value = "提交自动任务",
            notes = "提交自动任务 taskId"
    )
    public ResultMsg<String> saveAutoSubmitTask(@RequestParam @ApiParam(value = "任务ID", required = true) String taskId,
                                                @RequestParam(required = false) @ApiParam(value = "用户ID userId") String userId,
                                                @RequestParam(required = false) @ApiParam(value = "bizId") String bizId) throws Exception {
        EtechBpmHelper etechBpmHelper = AppUtil.getBean(EtechBpmHelper.class);
        boolean bresult = etechBpmHelper.saveAutoSubmitTask(taskId, userId, bizId);
        return ResultMsg.SUCCESS("调用结果："+bresult);
    }

}
